<?php
/**
 * Database Manager
 * 
 * @author Alexey Strelnikoff <zog@zoggi.net>
 */

namespace Zoggi\Database;

/**
 * Класс для работы с MySQL базой данных
 * 
 * Пример использования:
 * <code>
 * 		$db = new DB();
 * 		$q = $db->query("SHOW TABLES");
 * 		while ( $row = $q->FetchRow() ) {
 * 			var_export($row);
 * 		}
 * </code>
 */
class Mysql {

	public $link;
	private $config = array();
	private $tables = array();
	private $prefix = '';

	/**
	 * Выполнять-ли автоподключение к БД
	 * 
	 * @var boolean
	 */
	public $autoConnect = true;

	/**
	 * Возвращает объект с подключением к базе данных
	 *
	 * @return Mysql
	 */
	public function __construct() {
		
	}

	/**
	 * Устанавливает конфигурацию для раоты с базой данных
	 * Заполняет $this->config
	 *
	 * @param array $config Массив(host,user,password,base,charset)
	 * @return void
	 */
	public function setConfig( $config ) {
		$this->config = &$config;
	}

	/**
	 * Устанавливает имена таблиц, для замены placeholder'ов
	 * Заполняет $this->tables
	 *
	 * @param array $tables Массив таблиц
	 * @return void
	 */
	public function setTables( array $tables ) {
		foreach ( $tables as $tableId => $table ) {
			$this->tables['`{' . $tableId . '}`'] = '`' . $table . '`';
		}
	}

	/**
	 * Устанавливает префикс, с которого будут начинаться все имена таблиц
	 * 
	 * @param string $prefix Префикс таблиц
	 */
	public function setPrefix( $prefix ) {
		$this->prefix = $prefix;
	}

	/**
	 * Подключение к базе MySQL
	 * @return void
	 */
	public function connect( $host = NULL, $user = NULL, $password = NULL, $base = NULL, $charset = NULL ) {

		$newLink = true;

		if ( !$host ) {
			$host = &$this->config['host'];
		}
		if ( !$user ) {
			$user = &$this->config['user'];
		}
		if ( !$password ) {
			$password = &$this->config['password'];
		}
		if ( !$base ) {
			$base = &$this->config['base'];
		}
		if ( !$charset ) {
			$charset = &$this->config['charset'];
		}

		$this->link = mysql_connect($host, $user, $password, $newLink);
		if ( !$this->link ) {
			trigger_error(mysql_error(), E_USER_ERROR);
			return false;
		}

		$this->selectDB($base);

		if ( $charset ) {
			mysql_query("SET CHARACTER SET '" . $charset . "'", $this->link) or trigger_error(mysql_error(), E_USER_WARNING);
			mysql_query("SET NAMES '" . $charset . "'", $this->link) or trigger_error(mysql_error(), E_USER_WARNING);
		}
		return true;
	}

	/**
	 * Подключается к базе данных $dbName используя коннект $this->link
	 * 
	 * @param string $dbName Имя БД
	 * @return boolean
	 */
	public function selectDB( $dbName ) {

		if ( !mysql_select_db($dbName, $this->link) ) {
			trigger_error(mysql_error(), E_USER_ERROR);
			return false;
		}
		return true;
	}

	/**
	 * Делает запрос к базе данных и возвращает результат
	 *
	 * @param string $queryString
	 *
	 * @return MysqlQuery
	 */
	public function query( $queryString ) {
		if ( $this->autoConnect && !$this->link )
			$this->Connect();
		$queryString = $this->prepareQuery($queryString);

		$q = mysql_query($queryString, $this->link) or trigger_error("Can't execute query \"" . mysql_error($this->link) . "\"", E_USER_WARNING);
		if ( $q ) {
			return new MysqlQuery($q);
		} else {
			return false;
		}
	}

	/**
	 * Делает запрос к базе данных и возвращает результат
	 *
	 * @param string $queryString Строка SQL запроса
	 *
	 * @return MysqlQuery
	 */
	public function unbufferedQuery( $queryString ) {
		$queryString = $this->prepareQuery($queryString);

		$q = mysql_unbuffered_query($queryString, $this->link) or trigger_error(mysql_error() . "\n" . $queryString, E_USER_ERROR);
		return new MysqlQuery($q);
	}

	/**
	 * Возвращает ID созданный последней операцией INSERT (or REPLACE)
	 * 
	 * @return int
	 */
	public function insertedId() {
		return mysql_insert_id($this->link);
	}

	/**
	 * Заменяет в запросе вхождение `{таблица}` на `таблица из $this->table`, 
	 * а если $this->table пустое, то пробудет использовать $this->prefix
	 * 
	 * @param string
	 *
	 * @return string
	 */
	protected function prepareQuery( $queryString ) {
		if ( sizeof($this->tables) ) {
			$queryString = strtr($queryString, $this->tables);
		} elseif ( $this->prefix ) {
			$queryString = preg_replace("/`\{(.*?)\}`/is", $this->prefix . "\\1", $queryString);
		} else {
			$queryString = strtr($queryString, array('`{' => '`', '}`' => '`'));
		}

		return $queryString;
	}

	/**
	 * Returns mysql_real_escape_string
	 * 
	 * @param string $string Строка, которая будет экранирована
	 * @return string
	 */
	public function escape( $string ) {
		if ( $this->autoConnect && !$this->link )
			$this->Connect();
		return mysql_real_escape_string($string, $this->link);
	}

	/**
	 * Returns mysql_affected_rows()
	 * 
	 * @return int
	 */
	public function affectedRows() {

		return mysql_affected_rows($this->link);
	}

}